package com.example.wac.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.example.wac.annotation.RequestBodyAddParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author wuancheng
 * @description RequestBodyAdvice处理请求体通知 ResponseBodyAdvice处理返回体通知
 * @date 2022-05-09 20:06:00
 */

@Slf4j
@ControllerAdvice(basePackages = "com.example.wac.controller")
public class RequestBody extends RequestBodyAdviceAdapter {

    /**
     * 此处如果返回false , 则不执行当前Advice的业务
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    /**
     * 读取参数后执行
     */
    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
                                           Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        // 根据注解添加自定义参数 且controller必须有@RequestBody
        RequestBodyAddParam annotation = AnnotationUtils.findAnnotation(parameter.getMethod(), RequestBodyAddParam.class);
        boolean flag = false;
        if (annotation != null){
            flag = true;
        }
        // 添加自定义参数
        MyHttpInputMessage myHttpInputMessage = new MyHttpInputMessage(inputMessage,flag);
        return myHttpInputMessage;
    }

    /**
     * 无请求时的处理
     */
    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return body;
    }

    /**
     * 这里实现了HttpInputMessage 封装一个自己的HttpInputMessage
     */
    class MyHttpInputMessage implements HttpInputMessage {
        private HttpHeaders headers;
        private InputStream body;

        public MyHttpInputMessage(HttpInputMessage inputMessage, boolean flag)
                throws IOException {
            String reqJson = IOUtils.toString(inputMessage.getBody(), String.valueOf(StandardCharsets.UTF_8));
            HashMap<String, Object> dto = JSONObject.parseObject(reqJson, (Type) Map.class);
            if (flag){
                dto.put("body","测试AvoidResubmit注解通过RequestBodyAdviceAdapter添加参数");
            }
            this.headers = inputMessage.getHeaders();
            this.body = IOUtils.toInputStream(JSONObject.toJSONString(dto), String.valueOf(StandardCharsets.UTF_8));
        }

        @Override
        public InputStream getBody() {
            return body;
        }

        @Override
        public HttpHeaders getHeaders() {
            return headers;
        }
    }
}
